home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / lisp207.arc / PC-LISP.DOC < prev    next >
Text File  |  1986-03-26  |  75KB  |  1,588 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.           
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.                    A GUIDE TO THE PC-LISP INTERPRETER  (V2.07)
  18.                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  19.  
  20.                              By Peter Ashwood-Smith  
  21.                              ~~~~~~~~~~~~~~~~~~~~~~ 
  22.  
  23.                              University of Toronto,     
  24.                              ~~~~~~~~~~~~~~~~~~~~~
  25.  
  26.                                 Ontario, Canada.                
  27.                                 ~~~~~~~~~~~~~~~
  28.              
  29.  
  30.                                  
  31.                                  
  32.              With thanks to Brian Robertson for the math functions.
  33.  
  34.                             
  35.                                    Feb 01/86.
  36.  
  37.  
  38.  
  39.  
  40.  
  41.                         email: petera!utcsri or br!utcsri
  42.  
  43.                            mail:  Peter Ashwood-Smith
  44.                             #811, 120 St. Patrick St. 
  45.                                 Toronto, Ontario,
  46.                                      Canada,
  47.                                     M5T-2X7.
  48.  
  49.                              phone: (416) 593-7574.
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.                                         1
  62.  
  63.  
  64.  
  65.              INTRODUCTION
  66.              ~~~~~~~~~~~~
  67.              PC-LISP  is  a small implementation of LISP for  any  MS-DOS 
  68.         machine.  While  small,  it  is capable of running  a  reasonable 
  69.         subset  of Franz LISP.  It  is not 100% compatible with Franz but 
  70.         the functions have the same names and do the same things as Franz 
  71.         when  possible.  This is version 2.07 and is the result of  about 
  72.         1.5 years of work. Version 2.07 has these features:    
  73.              
  74.                   - types float, alpha, list, and port, function bodies 
  75.                     lambda, nlambda and macro.   
  76.              
  77.                   - full garbage collection of all types.     
  78.  
  79.                   - compacting, relocating heap space for all strings.     
  80.  
  81.                   - shallow binding techniques for O(1) symbol value
  82.                     lookup. (Dynamic scoping).  
  83.              
  84.                   - access to some MSDOS BIOS graphics routines.
  85.             
  86.                   - sufficient built in functions to allow implementation
  87.                     in LISP of most Franz or other functions. Includes
  88.                     prog,eval,apply,defun and def. 
  89.  
  90.                   - stack overflow detection & full error checking
  91.                     on all calls, tracing of user defined functions,
  92.                     and dumping of stack via (showstack).
  93.  
  94.                   - One level of break from which bindings at point
  95.                     of error can be seen.
  96.  
  97.                   - Access to as much (non extended) memory as you've 
  98.                     got and control over how this memory is spread 
  99.                     among the various data types.
  100.                        
  101.                   - Requires a bare minimum of 256K but the garbage    
  102.                     collection frequency is most bearable with 512K+.
  103.  
  104.              This version is ShareWare.  The idea is that you can make as 
  105.         many  copies as you like and distribute them to anyone or any BBS 
  106.         you please,  the more the better.  My only requests are that  you 
  107.         not  use  it  for profit of any kind,  or remove the  name(s)  of 
  108.         myself  or  any contributing authors from the program  header  or 
  109.         from  this  manual.  If you decide that you like the program then 
  110.         send  us  15$ to contribute to future development  costs.  Future 
  111.         development will consist of adding more types including  strings, 
  112.         arrays and the functions that operate on them. If I have time and 
  113.         there is enough interest I may also add a compiler.
  114.  
  115.             The  program  is  written 98% in C using the Lattice  C  2.03 
  116.         compiler  with some extra assembly language routines to  make  up 
  117.         for  the otherwise excellent Lattice compiler and libraries.  The 
  118.         math  library was written for me by Brian Robertson also  of  the 
  119.         University of Toronto.
  120.  
  121.  
  122.                                         2
  123.  
  124.  
  125.  
  126.              A WARNING
  127.              ~~~~~~~~~
  128.              As I mentioned previously this program was compiled with the 
  129.         Lattice  C compiler,  as such the program contains code to  which 
  130.         Lattice Inc.  holds a copyright.  If you sell it I can  only  get 
  131.         angry  but  Lattice could take you to court.  And,  as  with  all 
  132.         software  you  use  it  at your own risk.  I  will  not  be  held 
  133.         responsible  for  loss of any kind as a result of the correct  or 
  134.         incorrect use of this program.
  135.                   
  136.              A NOTE
  137.              ~~~~~~
  138.              The  rest  of this manual assumes some  knowledge  of  LISP, 
  139.         MSDOS and a little programming experience. If you are new to LISP 
  140.         or programming in general you should work your way through a book 
  141.         on  LISP such as LISPcraft by Robert Wilensky.  You can  use  the 
  142.         interpreter  to  run  almost all of the examples in  the  earlier 
  143.         chapters.  I  obviously  cannot attempt to teach  you  LISP  here 
  144.         because  it  would require many hundreds of pages and  there  are 
  145.         much better books on the subject than I could write.  Also, there  
  146.         are  other good books on Franz LISP besides LISPcraft so I am not 
  147.         endorsing it. It just happens to be the book that I use.
  148.  
  149.              EXAMPLE FUNCTIONS INCLUDED IN EXTFUNC.L
  150.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  151.              For  those of you that are like me and hate to read a manual 
  152.         you  can  take a look in the file  EXTFUNC.L  which  should  have 
  153.         come  with the interpreter.  This file contains lots of  function 
  154.         definitions  to help fill the gap between PC and Franz  LISP.  It 
  155.         also contains a small Turtle Graphics demonstration.  If you want 
  156.         to  start learning LISP or try out the demonstration  you  should 
  157.         start  PC-LISP by typing "PC-LISP EXTFUNC.L"  from  MS-DOS.  Then 
  158.         wait a bit until you see the "-->" prompt. Be patient if you have 
  159.         512K or more memory because it takes a few seconds for PC-LISP to 
  160.         organize your memory. If you only have a 256K machine, now is the 
  161.         time to start thinking about an extra 256K.  PC-LISP will be much 
  162.         faster not having to garbage collect all the time. Anyway you now 
  163.         have  the  prompt  "-->" and EXTFUNC.L  is  loaded.  To  run  the 
  164.         graphics  demo you just type "(GraphicsDemo)" without the quotes, 
  165.         followed by ENTER. You must have a graphics adapter for this demo 
  166.         to  run.  Don't  even  try  it if your machine  has  no  graphics 
  167.         capability. (Graphics are slow but thats the price of portability 
  168.         across MS-DOS machines).  Note that if you want to start learning 
  169.         LISP  from  a  book  such as  LISPcraft,  you  should  also  load 
  170.         "EXTFUNC.L"  as functions that are referenced in the first couple 
  171.         of  chapters are defined in this file.  The functions defined  in 
  172.         EXTFUNC.L are not very effecient so you may want to replace  them 
  173.         with your own definitions.
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.                                         3
  184.  
  185.  
  186.  
  187.              USERS GUIDE
  188.              ~~~~~~~~~~~
  189.              The  PC-LISP program is self contained.  To run it just type 
  190.         the command PC-LISP or whatever you called it.  When it starts it 
  191.         will start grabbing memory in chunks of 16K each.  These will  be 
  192.         allocated  to the three basic data types in percentages that  you 
  193.         can specify via 2 environment variables.  The default is that 25% 
  194.         of  the  memory will be allocated for alpha atoms.  15%  will  be 
  195.         allocated for heap space,  and the rest for cons,port,  and float 
  196.         cells.  If  you  set  the  environment  variables  LISP%HEAP  and 
  197.         LISP%ALPH  to  an integer between 1 and 90 these will become  the 
  198.         new  percentages for the heap and alpha  respectively,  the  rest 
  199.         going to cons,  port,  and float cells. Note that the percentages 
  200.         are only accurate to the nearest 16K boundary. In other words the 
  201.         set of 16K blocks are divided among the three types as closely to 
  202.         the percentages that you specify as possible.   PC-LISP will then 
  203.         print  the  banner message,  the total memory available  and  the 
  204.         percentages that are allocated to each object. Next it will begin 
  205.         to read the parameters from the command line.  The command  usage 
  206.         is:
  207.                                               *
  208.              PC-LISP [=n..n] [ [+s][-s] file ]
  209.              
  210.              The  optional parameter =nnnn is the Lattice set stack  size 
  211.         option.  It  is preset to 32K and cannot be set smaller.  You may 
  212.         set it larger up to 64K if you wish.  A 32K stack gives you about 
  213.         466 recursive calls,  50K = 731 calls, 60K = 878 calls, and 64K = 
  214.         936  calls.  The  Lattice C compiler does not generate code  that 
  215.         will handle stacks larger than 64K.
  216.                   
  217.              The  +s  and  -s options turn on and  off  the  printing  of 
  218.         statistical  information while the file 'file' is being read  and 
  219.         evaluated.  Statistical  information is just a line telling  what 
  220.         percentage of cell,  alpha and heap space you have used.  Garbage 
  221.         collection occurs at 100% use for a given object. The statistical 
  222.         info  is  useful  to  see  just  how  efficient/inefficient  your 
  223.         functions  are.  You can get the same information in list form by 
  224.         calling  the PC-LISP function (memstat) where the  three  numbers 
  225.         returned  correspond to the percentage of cell,  alpha  and  heap 
  226.         space used so far.
  227.  
  228.              The files on the command line are processed one by one. This 
  229.         consists of reading each list in the file and evaluating it.  The 
  230.         results  are  not printed on the console.  Finally when  all  the 
  231.         files  have  been processed you will find yourself with the  LISP 
  232.         top level prompt '-->'. Typing control-Z and ENTER (MS-DOS end of 
  233.         file) when you see the '-->' prompt will cause PC-LISP to exit to 
  234.         whatever program called it.   If an error occurs you will see the 
  235.         prompt 'er>'.  For more info see the 'TERMINATION OF  EVALUATION' 
  236.         section of this manual and the commands (showstack), (trace), and 
  237.         (untrace).
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.                                         4
  245.  
  246.  
  247.  
  248.              SYNTAX
  249.              ~~~~~~ 
  250.              You  will  now be in the LISP interpreter and can  start  to 
  251.         play  with  it.  Basically  it is expecting you  to  type  an  S-
  252.         expression. Where an S-expression is an atom, or a list and:   
  253.  
  254.              An atom may be one of three kinds. It may be an alpha atom ,  
  255.         a  real number atom,  or a literal alpha atom.  An alpha atom  is 
  256.         just  a  letter  followed by letters/digits and  certain  special 
  257.         symbols.  There  may be no more than 254 characters in the  alpha 
  258.         atom.  To allow you to enter any text as an atom you may  delimit  
  259.         the  atom  with |'s.  These will define a literal alpha  atom  in 
  260.         which  you may place any character between the delimiters (except 
  261.         |  itself).  A real atom is just as you might think  an  optional 
  262.         plus  or  minus sign followed by a sequence of  digits,  followed 
  263.         optionally by a radix point and more digits.  Sorry,  exponential 
  264.         notation is not supported. It should get into the next version.
  265.              
  266.              A  list is just a left ( followed by a of sequence of  atoms 
  267.         or lists followed by a right ).  A list may also be a sequence of 
  268.         atoms or lists followed by a '.' followed by an atom followed  by 
  269.         a right parenthisis ).  This is called a dotted pair and it means 
  270.         that the CAR and CDR of a list are both atoms.  Note that a space 
  271.         on  either  side of the dot is essential syntactically.  You  may 
  272.         optionally  place  [  and  ]  in  the  list  to  represent  meta-
  273.         parenthesis. Basically the ] just closes all open lists up to the 
  274.         nearest  [,  or to the beginning of the list if no [ is  present. 
  275.         Here are some example legal lists.
  276.  
  277.              (now is (the . time))         ; dotted pair (the . time)
  278.              (1 now16 (is (the (time ]     ; the ] closes all 4 ('s
  279.              (car [quote(a b c d])         ; the ] closes 2 ('s to ]    
  280.              (ThisIsBiggerAtom012345678)   ; Upper case is ok    
  281.              ()                            ; empty list is equiv to 'nil
  282.              (1 (-2.2 +3.333))             ; some numbers all floats!
  283.              ((((((|all one atom|]         ; "all one atom" spaces too!
  284.  
  285.              Note that you are allowed to mix any number of spaces, line-
  286.         feeds,  carriage returns,  form feeds, tabs etc. into your input. 
  287.         Comments may start at any point in a line and will continue until 
  288.         the end of the line as shown in the above example lists.
  289.  
  290.              READ MACRO QUOTE
  291.              ~~~~~~~~~~~~~~~~
  292.              PC-LISP  supplies one read macro called 'quote' and  written 
  293.         using the little ' symbol.  (User read macros in later  versions) 
  294.         This  read  macro  is just a short hand way of writing  the  list 
  295.         (quote  XX).  Where  XX  is what follows the  '.  Here  are  some 
  296.         examples  of  what  the read macro will do to your  input  before 
  297.         passing it to the evaluator.
  298.  
  299.              'apples        -- goes to -->    (quote apples)
  300.              '|too late|                      (quote |too late|)
  301.              '(1 2 3)                         (quote (1 2 3))
  302.  
  303.  
  304.  
  305.                                         5
  306.  
  307.  
  308.  
  309.              SYNTAX ERRORS
  310.              ~~~~~~~~~~~~~
  311.              When  you  enter  a list which is not correctly  nested  the 
  312.         interpreter  will  return  the  wonderfully  informative  'syntax 
  313.         error'  message.  You will have to figure out where it is in  the 
  314.         input  list.  Note that if you do not finish entering a list,  ie 
  315.         you put one too few closing )'s on the end,  the interpreter will 
  316.         wait  until you enter it before continuing.  If you are not  sure 
  317.         what has happened just type "]]" and all lists will be closed and 
  318.         the  interpreter will try to do something with the list.  If  you 
  319.         are running input from a file the interpreter will detect the end 
  320.         of  file  and  give  you a 'syntax error' because  the  list  was 
  321.         unclosed.
  322.  
  323.              EVALUATING S-EXPRESSIONS
  324.              ~~~~~~~~~~~~~~~~~~~~~~~~
  325.              An  S-expression may be an atom or a list.  If it is an atom 
  326.         the  evaluation of it is its current binding. Most atoms are  not 
  327.         bound  to begin with so just entering an atom will result in  the 
  328.         error  'unbound  atom'.  Float atoms are bound  to  their  actual 
  329.         values so when you enter 2 you will get 2 back again.  Evaluating 
  330.         a  list  consists of calling the function named or given  by  the 
  331.         first  element  in the list with parameters given by the rest  of 
  332.         the list.  For example there is a function called '+' which takes 
  333.         any number of float  values  and returns their sum. So:
  334.  
  335.              -->(+ 2 4 6 8)
  336.  
  337.              Would  return  the result of 2+4+6+8 ie  20.   We  can  also 
  338.         compose these function calls by using list nesting.  For  example 
  339.         we can subtract  2+4 from 6+8 as follows:
  340.  
  341.              -->(- (+ 6 8) (+ 2 4))
  342.  
  343.              We  can  also  perform operations on other types  of  atoms. 
  344.         Suppose  that  we wanted to reverse the list (now is  the  time). 
  345.         There is a built in function called 'reverse' that does just what 
  346.         we want. So we could try typing.
  347.              
  348.              -->(reverse (now is the time))
  349.  
  350.              But the interpreter will be confused!  It does not know that 
  351.         'now'  is data and not a function taking arguments   'is',  'the' 
  352.         and  'time'.  We must use the function 'quote' which returns  its 
  353.         arguments unevaluated, hence its name "quote".
  354.  
  355.              -->(reverse (quote (now is the time)))
  356.  
  357.              Will  give us the desired result (time the is now).  But  we 
  358.         can  do  the  same  thing  without  using  the  (quote)  function 
  359.         directly.  Remember the read macro ' above?  Well it will replace 
  360.         the  entry  '(now is the time) with (quote (now  is  the  time)). 
  361.         Hence we type:
  362.  
  363.              -->(reverse '(now is the time))
  364.  
  365.  
  366.                                         6
  367.  
  368.  
  369.  
  370.              EVALUATING S-EXPRESSIONS CONT'D
  371.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  372.              This gives us the correct result without as much typing. You 
  373.         will  note that the subtraction of 2+4 from 6+8 could  also  have 
  374.         been entered as:
  375.              
  376.              -->(- (+ '6 '8) (+ '2 '4))
  377.  
  378.              However,   the  extra  's  are  redundant  because  a  float 
  379.         evaluates to itself. In general a LISP expression is evaluated by 
  380.         first  evaluating each of its arguments,  and then  applying  the 
  381.         function to the arguments,  where the function is the first thing 
  382.         in the list.  Remember that evaluation of the function (quote s1) 
  383.         returns  s1 unevaluated.   LISP will also allow the function name 
  384.         to be replaced by a function body called a lambda expression.  So 
  385.         a legal input to the interpreter could be:
  386.  
  387.              -->((lambda(x)(+ x 10)) 14)
  388.  
  389.              Which would be processed as follows. First the parameters to 
  390.         the lambda expression are evaluated.  That just 14. Next the body 
  391.         of the lambda expression is evaluated but with the value 14 bound 
  392.         to  the formal parameter given in the lambda expression.  So  the 
  393.         body evaluated is (+ x 10) where x is bound to 14.  The result is 
  394.         just 24. Note that lambda expressions can be passed as parameters 
  395.         as  can  built in functions or user defined functions.  So I  can 
  396.         evaluate the following expression. 
  397.  
  398.              -->((lambda(f x)(f (car x))) '(lambda(l)(car l)) '((hi)))
  399.  
  400.              Which evaluates as follows. The parameters to the call which 
  401.         are   the   expressions  '(lambda(l)(cdr  l))  and  '((hi))   are 
  402.         evaluated. This results in the expressions being returned because 
  403.         they are quoted.  These are then bound to 'f and 'x  respectively 
  404.         and  the body of the first lambda expression is  evaluated.  This 
  405.         means  that  the  expression ((lambda(l)(car l))(car  ((hi)))) is 
  406.         evaluated. So again the parameters to the function are evaluated. 
  407.         Since  the  only  parameter  is  (car  ((hi)))  it  is  evaluated 
  408.         resulting  in  (hi).  This  is then bound to l  and  (car  l)  is 
  409.         evaluated giving "hi".
  410.  
  411.              PC-LISP  is also capable of handling lambda expressions with 
  412.         multiple  bodies,  nlambda  expressions with multiple bodies  and 
  413.         labeled  lambda  and  nlambda  expressions.   See  the  Built  In 
  414.         Functions  Section which follows for more details on  lambda  and 
  415.         nlambda. A slightly restricted macro form is also permitted.  For 
  416.         information on macros see the MACRO section of the manual.
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.                                         7
  428.  
  429.  
  430.  
  431.              TERMINATION OF EXPRESSION EVALUATION
  432.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  433.              There are three distinct ways that evaluation can terminate. 
  434.         First, evaluation can end naturally when there is no more work to 
  435.         do.  In  this  case the resulting S-expression is printed on  the 
  436.         console and you are presented with the prompt "-->".  Second, you 
  437.         can request premature termination by hitting the CONTROL-BREAK or 
  438.         CONTROL-C keys simultaneously (hereafter referred to as  CONTROL-
  439.         BREAK).  Note  that this will only interrupt list evaluation,  it 
  440.         will   not  interrupt  garbage  collection  which  continues   to  
  441.         completion.  So,  if  you hit CONTROL-BREAK or CONTROL-C and  you 
  442.         don't  get  any response,  wait a second or two because  it  will 
  443.         respond  after garbage collection ends.  Finally,  execution  can 
  444.         terminate  when  PC-LISP detects a bad parameter to  a  built  in 
  445.         function,  a stack overflows, a division by zero is attempted, or 
  446.         an atom is unbound etc. In all cases but a normal termination you 
  447.         will be returned to a break error level.  This is when the prompt 
  448.         looks  like  'er>'.  This means that variable bindings are  being 
  449.         held  for you to examine.  So if the evaluation aborts  with  the 
  450.         message  "error in built in function [car]",  you can examine the 
  451.         atom  bindings  that were in effect when this error  occurred  by 
  452.         typing the name of the atom desired.  This causes its binding  to 
  453.         be displayed. When you are finished with the break level just hit 
  454.         CONTROL-Z  plus  ENTER and you will be placed back in the  normal 
  455.         top  level  and all bindings that were non global will  be  gone. 
  456.         Note  you can do anything at the break level that you can  do  at 
  457.         the top level. If further errors occur you will stay in the break 
  458.         level and any bindings at the time of the second error will be in 
  459.         effect  as  well  as  any bindings that were  in  effect  at  the 
  460.         previous  break level.  If bindings effecting atoms whose  values 
  461.         are being held in the first break level are rebound at the second 
  462.         break  level these first bindings will be hidden by the secondary 
  463.         bindings.
  464.  
  465.              It  is worth noting that when an error occurs in  'eval'  or 
  466.         'apply'  it  usually  means  that a  parameter  is  being  passed 
  467.         incorrectly  to a user defined function.  Since the error message 
  468.         will  refer  to a built in function when it tells  you  about  an 
  469.         error  you  will have to figure out which one of  your  functions 
  470.         made that call.
  471.  
  472.              It  is  also useful to know what the  circumstances  of  the 
  473.         failure  were.  You can display the last 20 evaluations with  the 
  474.         command  (showstack).  This will print the stack from the top  to 
  475.         the  20th  element  of the stack.  This gives  you  the  path  of 
  476.         evaluation  that lead to the error.  For more information on  the 
  477.         (showstack)  command  look  in the section  FUNCTIONS  WITH  SIDE 
  478.         EFFECTS OR THAT ARE EFFECTED BY SYSTEM.
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.                                         8
  489.  
  490.  
  491.  
  492.              THE BUILT IN FUNCTIONS AND VARIABLES
  493.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  494.  
  495.              Following is a list of each built in function. I will denote
  496.         the  allowed  arguments  as follows:  
  497.  
  498.            - a1...aN are alpha atom parameters. 
  499.  
  500.            - f1...fN are float atom parameters.
  501.  
  502.            - l1...lN are list expression parameters.
  503.  
  504.            - p1...pN are port atom parameters.
  505.  
  506.            - s1...sN  are  S-expressions (any atom type or list)
  507.  
  508.            - {a|d}+  means  any sequence of characters of length  greater 
  509.              than  0 consisting of a's and d's in any  combination.  This 
  510.              defines  the car,cdr,cadr,caar,cadar...  function  class  as 
  511.              follows: "c{a|d}+r".
  512.  
  513.            - [a1], [f1], [l1], [p1], [s1], etc... are optional parameters 
  514.              of  the indicated type.  A default will be provided if  they 
  515.              are  not  present  in the parameter list for  the  indicated      
  516.              function.
  517.              
  518.            - *a1*, *f1*, *l1*, *p1* or *s1* this means that the arguments 
  519.              of the function are NOT evaluated prior to the function call 
  520.              hence it is not necessary to quote them.
  521.  
  522.              For  the  simpler functions I will describe  the   functions 
  523.         using  a sort of "if (condition) result1 else  result2"  notation 
  524.         which should be pretty obvious to most people. For functions that 
  525.         are a little more complex I will give a short English description 
  526.         and  perhaps  an  example.  If the example code shows  the  '-->' 
  527.         prompt  you  should  be able to type exactly  what  follows  each 
  528.         prompt  and get the same responses from PC-LISP.  If the  example 
  529.         does not show a '-->' prompt the example is a code fragment which 
  530.         requires additional code to function.
  531.  
  532.              The  functions  are placed into 7 categories.  These are  as 
  533.         follows: The math functions, the boolean functions, list and atom 
  534.         creators and selectors,  file I/O functions,  functions with side 
  535.         effects or that are effected by state of system,  list evaluation 
  536.         control  functions and the MSDOS bios calls for graphics  output. 
  537.         Note  that the BIOS calls are still  experimental.   Specifically 
  538.         the  line drawing algorithm does not draw lines as smooth  or  as 
  539.         fast as I would like. This should be fixed by the next release.
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.                                         9
  550.  
  551.  
  552.  
  553.              THE MATH FUNCTIONS
  554.              ~~~~~~~~~~~~~~~~~~
  555.  
  556.              The  functions  manipulate floats. They are mostly  obvious. 
  557.         Note that these function work on floats while the Franz functions 
  558.         work  on  -numbers-.  Anywhere in PC-LISP where the parameter  is 
  559.         giving  position  or ordinal information the nearest  integer  to 
  560.         the  float parameter is taken as the correct value.  
  561.  
  562.              (abs  f1)    ----> absolute value of f1 is returned.
  563.              (acos f1)    ----> arc cosine of f1 is returned.
  564.              (asin f1)    ----> arc sine of f1 is returned.
  565.              (atan f1 f2) ----> arc tangent of ( f1 divided by f2 ).
  566.              (cos f1)     ----> cosine of f1, f1 is radians
  567.              (exp f1)     ----> returns e to the power f1.
  568.              (expt f1 f2) ----> returns f1**f2 using: exp(f2*log(f1))
  569.              (fact f1)    ----> returns factorial of nearest int to f1.
  570.              (log f1)     ----> natural logarithm of f1.
  571.              (log10 f1)   ----> base 10 logarithm of f1.
  572.              (max f1..fn) ----> largest of f1...fn.
  573.              (min f1..fn) ----> smallest of f1...fn.
  574.              (mod f1 f2)  ----> r1 modulo r2.
  575.              (random [f1])----> random float in 0..32K or 0..f1
  576.              (sin f1)     ----> sine of f1, f1 is radians.
  577.              (sqrt f1)    ----> square root of f1.
  578.              (* f1 .. fn) ----> f1*f2*f3*.....fn (or 1 if n = 0)  
  579.              (+ f1 .. fn) ----> f1+f2+f3+.....fn (or 0 if n = 0)  
  580.              (- f1 .. fn) ----> f1-f2-f3-.....fn (or 0 if n = 0)  
  581.              (/ f1 .. fn) ----> f1/f2/f3/.....fn (or 1 if n = 0)
  582.              (< f1 f2)    ----> if (f1 < f2) t else nil;
  583.              (= f1 f2)    ----> if (f1 = f2) t else nil;
  584.              (> f1 f2)    ----> if (f1 > f2) t else nil;
  585.  
  586.              One  thing worth noting is that when you compare two  floats 
  587.         you must use = or equal.  You cannot use eq because the two float 
  588.         values will almost certainly be stored in different cells even if 
  589.         they  have the same value.  Hence eq will return nil because they 
  590.         are not the same object.  Note that Franz will return 't when you 
  591.         compare  two  fixnums using eq because car and cdr  pointers  are 
  592.         used  to  store the actual fixnum itself hence they appear to  be 
  593.         the same object.  This is an interpreter dependent trick and  PC-
  594.         LISP does not do it.
  595.  
  596.              Consider this example which computes the sum of the cubes of 
  597.         a list of floats called X which is setq'ed to (1 2 3 4 5):
  598.  
  599.              -->(setq X '(1 2 3 4 5))
  600.              (1 2 3 4 5)
  601.              -->(eval (cons '+ (mapcar '* X X X)))
  602.              225
  603.  
  604.              It  operates as follows:  First mapcar computes the products 
  605.         1*1*1, 2*2*2,... 5*5*5 and creates the list (1 8 27 64 125). Then 
  606.         cons  splices  a '+ onto the front creating (+ 1 8  27  64  125). 
  607.         Finally eval gets the list and computes the result 225.
  608.  
  609.  
  610.                                        10
  611.  
  612.  
  613.  
  614.              THE BOOLEAN FUNCTIONS
  615.              ~~~~~~~~~~~~~~~~~~~~~
  616.  
  617.              These functions all return boolean values. The values 't and 
  618.         'nil  represent  true  and false respectively. 't  and  'nil  are 
  619.         predefined atoms whose bindings are exactly themselves. Note that 
  620.         'nil  is equivalent to the empty list ().  It is the only  object 
  621.         that is both at atom and a list.
  622.  
  623.  
  624.              (alphalessp a1 a2) ---> if (ASCII a1 < a2) t else nil;
  625.              (atom s1)          ---> if (s1 of type atom) t else nil;
  626.              (and s1 s2 .. sN)  ---> if (a1...aN all != nil) t else nil;
  627.              (boundp a1)        ---> if (a1 bound) (a1.eval(a1)) else nil;
  628.              (eq s1 s2)         ---> if (s1 & s2 same object) t else nil;
  629.              (equal s1 s2)      ---> if (s1 looks like s2) t else nil;
  630.              (floatp s1)        ---> if (s1 of type float) t else nil;
  631.              (listp s1)         ---> if (s1 of type list) t else nil;
  632.              (not s1)           ---> if (s1 != nil) nil else t;
  633.              (null s1)          ---> if (s1 != nil) nil else t;  
  634.              (or s1 s2 .. sN)   ---> if (any si != nil) t else nil;
  635.              (portp s1)         ---> if (s1 of type port) t else nil;
  636.  
  637.  
  638.              Where ASCII a1 < a2 means that string a1 comes before string 
  639.         a2  using  the ASCII codes for the characters in both a1 and  a2. 
  640.         And,  a1 bound means that a1 has been assigned a value.  And,  s1 
  641.         looks  like s2 means that s1 and s2 have the same list  structure 
  642.         and the leaves point to the same atoms.  And,  s1 and s2 the same 
  643.         object  means  that they are exactly the same list  or  the  same 
  644.         atom.
  645.  
  646.              Note  that  (eq  'a 'a) will always return  't  because  the 
  647.         object  'a is unique to the LISP interpreter.  On the other  hand 
  648.         the  call (eq '(a) '(a)) will always return 'nil because the  two 
  649.         parameters  '(a) and '(a) are distinct lists created by the  read 
  650.         function.  However  (equal '(a) '(a)) will return 't because  the 
  651.         two lists are of the same form and have the same leaves.
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.  
  670.  
  671.                                        11
  672.  
  673.  
  674.  
  675.              LIST & ATOM CREATORS AND SELECTORS
  676.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  677.              These functions will take lists and atoms as parameters  and 
  678.         return  larger  or  smaller lists or atoms.  They  have  no  side 
  679.         effects  on  the  LISP system nor are their results  affected  by 
  680.         anything other than the values of the parameters given to them.
  681.  
  682.              (append l1..ln)    ---> list made by joining all of l1..ln.
  683.  
  684.              (ascii f1)         ---> atom with name 'char' where 'char' 
  685.                                      has ordinal value f1:(0 < f1 < 255).
  686.  
  687.              (assoc a1 s2)      ---> if s2 is a list of (atom.value) pairs
  688.                                      then assoc --> (a1.value) from s2.
  689.  
  690.              (car l1)           ---> first element in l1
  691.  
  692.              (cdr l1)           ---> l1 without first element of l1.
  693.  
  694.              (c{a|d}+r l1)      ---> performs repeated car or cdr's on
  695.                                      l1 as given by reverse of {a|d}+.
  696.  
  697.              (cons s1 s2)       ---> list with s1 as 1st elem s2 is rest. 
  698.  
  699.              (explode a1)       ---> list of chars in name of a1.
  700.  
  701.              (exploden a1)      ---> list of ascii values of chars in a1.
  702.  
  703.              (implode l1)       ---> atom with name formed by compressing
  704.                                      all atom elements of l1.
  705.  
  706.              (length l1)        ---> float atom = # of elements of l1 
  707.  
  708.              (list s1 s2...sN)  ---> a list with elements (s1 s2 ...sN)
  709.  
  710.              (nth f1 l1)        ---> f1'th element of l1 (indexed from 0)
  711.  
  712.              (nthchar a1 f1)    ---> f1'th char in name of a1 (from 0) 
  713.  
  714.              (pairlis l1 l2 l3) ---> l1 is list of atoms. l2 is a list 
  715.                                      of S-expressions. l3 is a list of
  716.                                      ((a1.s1)....) The result is the
  717.                                      pairing of atoms in l1 with values
  718.                                      in l2 with l3 appended (see assoc).
  719.              
  720.              (quote *s1*)       ---> exactly s1 unevaled without changes.
  721.  
  722.              (reverse l1)       ---> the list l1, reversed at top level.
  723.              
  724.              (type s1)          ---> list,float,port,alpha or other as
  725.                                      determined by type of parameter s1.
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.                                        12
  733.  
  734.  
  735.  
  736.              FILE I/O FUNCTIONS
  737.              ~~~~~~~~~~~~~~~~~~
  738.              These  functions perform simple list/atom and character  I/O 
  739.         you must be careful when writing lists to files to terminate with 
  740.         a  new  line before closing the file.  Otherwise they  may  cause 
  741.         problems for some MS-DOS editors etc.  These functions operate on 
  742.         type  'port'  which  is  returned by 'fileopen'  and  which  when 
  743.         printed  is  just %file% where 'file' is the name  of  associated 
  744.         port.
  745.  
  746.              (close p1)            ---> closes the port p1 and returns t.
  747.  
  748.              (fileopen a1 a2)      ---> port to read write to/from to
  749.                                         file a1 using mode a2. Where
  750.                                         modes are 'r 'w 'rw 'rwa ...
  751.  
  752.              (load a1)             ---> The file a1 is read and all lists 
  753.                                         are  evaluated.  LISP  will  look 
  754.                                         first  for  file  a1,  then  a1.l
  755.                                         then for LIB/a1 and finally for
  756.                                         LIB/a1.l. Where LIB is the value
  757.                                         of the environment variable :
  758.                                         LISP%LIB
  759.  
  760.              (patom a1 [p1])       ---> print atom without delimiters
  761.                                         to port p1. Default to standard
  762.                                         output if p1 not present. returns
  763.                                         a1.
  764.  
  765.              (print s1 [p1])       ---> print list with delimiters on
  766.                                         atoms to p1 or standard out.
  767.  
  768.              (read [p1 [s1]])      ---> returns S-expression read from
  769.                                         p1 or standard input and returns
  770.                                         it or nil on end of file. If s1
  771.                                         is present it returns s1 on EOF.
  772.  
  773.              (readc [p1 [s1]])     ---> returns character read from p1
  774.                                         or standard input and returns it
  775.                                         or nil on end of file. If s1 is
  776.                                         present it returns s1 on EOF.
  777.  
  778.              
  779.              A word about delimiters.  Unless you use the patom  function 
  780.         all printing of atoms will be done in such a way that they can be 
  781.         read again and produce the same structure. This means that if the 
  782.         atom  was  originally  entered with the | delimiters it  will  be 
  783.         printed with them.  Or,  if you created an atom via an implode or 
  784.         ascii function call that has a funny value in it,  it will  print 
  785.         with  the  delimiters.  So if you want to print a prompt  on  the 
  786.         screen  with  spaces in it the best way is to enter  (patom  '|my 
  787.         prompt|).  Note also that 'r 'w and 'a stand for read,  write and 
  788.         append respectively.
  789.  
  790.  
  791.  
  792.  
  793.                                        13
  794.  
  795.  
  796.  
  797.              FUNCTIONS WITH SIDE EFFECTS OR THAT ARE EFFECTED BY SYSTEM
  798.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  799.              These  functions  will either have an effect on the way  the 
  800.         system behaves in the future or will give you a result about  the 
  801.         way  the system has behaved in the past and future calls will not 
  802.         necessarily give the same results.
  803.  
  804.              (def *a1* *l1*)    
  805.              ~~~~~~~~~~~~~~~    
  806.              a1 is a function name and l1 is a lambda,  nlambda or  macro 
  807.         body. The body is associated with the atom a1 from now on and can 
  808.         be used as a user defined function. Def returns a1.            
  809.  
  810.                -->(def first  (lambda(x)(car x)))
  811.                -->(def second (lambda(x)(first(cdr x))))
  812.                -->(def sideff (lambda(x)(print x)(caddar x))))
  813.                -->(def plus   (nlambda(l)(eval(cons '+ l))))
  814.                -->(def firstm (macro(l)(cons 'car (cdr l))))
  815.  
  816.              (defun *a1* [*a2*] *l1* *s1* *s2* ....*sN*)
  817.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  818.              Defun  will  do the same job as "def" except  that  it  will 
  819.         build the lambda or nlambda expression for you. a1 is the name of 
  820.         the function.  a2 if present must be one of expr or fexpr.  If it 
  821.         is  not  present it defaults to expr.  l1 is the list  of  formal 
  822.         parameters  which for an fexpr (nlambda) should contain one  atom 
  823.         formal  parameter  name.  s1...sn are bodies for  the  lambda  or 
  824.         nlambda  expression.  The  following  example produces  the  same 
  825.         effects as the above "def" calls.  Defun returns the atom name of 
  826.         the function that it defines. See MACROS for (defun x macro...)
  827.  
  828.                -->(defun first(x)(car x))
  829.                -->(defun second(x)(first(cdr x)))
  830.                -->(defun sideff(x)(print x)(caddar x)))
  831.                -->(defun plus fexpr(l)(eval(cons '+ l)))
  832.                -->(defun firstm macro(l)(cons 'car (cdr l)))
  833.  
  834.              (exit)
  835.              ~~~~~~
  836.              The  LISP interpreter will exit to MSDOS.  Depending on  how 
  837.         much  memmory  you  have it may ask for a system disk  to  reload 
  838.         COMMAND.COM.  Note  that the video mode will not be reset if  you 
  839.         call  (exit).  It will however be reset to 80x25B&W if  you  quit 
  840.         with a control-Z from the top level.  
  841.  
  842.              (gc)
  843.              ~~~~
  844.              Starts garbage collection of alpha and cell space. Returns t 
  845.  
  846.              (gensym [a1])
  847.              ~~~~~~~~~~~~~
  848.              Will  generate  a new alph atom whose name is  gnnnnn  where 
  849.         nnnnn will be different each time. It is guaranteed to generate a 
  850.         new atom.  If a1 is present then the atoms have the form (name of 
  851.         a1)nnnnn.
  852.  
  853.  
  854.                                        14
  855.  
  856.  
  857.  
  858.              FUNCTIONS WITH SIDE EFFECTS OR THAT ARE EFFECTED BY SYSTEM
  859.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  860.              CONT'D
  861.              ~~~~~~
  862.              (get a1 a2)
  863.              ~~~~~~~~~~~
  864.              Will  return  the value associated with property key a2   in 
  865.         a1's property list.  This value will have been set by a  previous 
  866.         call to (putprop a1 s1 a2). Example:
  867.  
  868.              -->(get 'frank 'lastname)
  869.  
  870.              (getd a1)
  871.              ~~~~~~~~~
  872.              Will return the lambda,  nlambda or macro expression that is 
  873.         associated  with  a1 or nil if no such expression  is  associated 
  874.         with a1.
  875.  
  876.              (getenv a1)
  877.              ~~~~~~~~~~~
  878.              Will  return  an atom whose print name is the string set  by 
  879.         environment variable a1. For example we can get the PATH variable 
  880.         setting  by entering (getenv 'PATH).  Note that these must be  in 
  881.         upper case for MSDOS.
  882.  
  883.              (hashtabstat)
  884.              ~~~~~~~~~~~~~
  885.              Will  return a list containing 250 float atoms.  Each  float 
  886.         atoms  value represents the number of elements in the bucket  for 
  887.         that hash location in the atom hash table. 250 is the size of the 
  888.         hash table. This is not especially useful for you but it gives me 
  889.         a  way of checking how the hashing function is  distributing  the 
  890.         atoms.  Large  bucket values will not effect any execution  times 
  891.         except  those of explode,  implode,  ascii and gensym.  In  other 
  892.         words only functions that create new atoms will be slowed down by 
  893.         poor  hashing.  Reading will always suffer from large hash bucket 
  894.         values.
  895.  
  896.              (memstat)      { not present in Franz }
  897.              ~~~~~~~~~
  898.              returns  three floats.  The first is the percentage of  cell 
  899.         space that is in use.  The second is the percentage of alpha cell 
  900.         space and the third is the percentage of heap space in use.  When 
  901.         any of these reach 100%, garbage collection will occur. Alpha and 
  902.         cell  space is collected together.  Heap space is only  collected 
  903.         when  you run out.  After garbage collection you will  see  these 
  904.         three  percentages  drop.  The alpha and cell percentages  should 
  905.         drop  to  tell  you how much memory is actually in  use  at  that 
  906.         moment.  The  heap  space when compacted and  gathered  will  not 
  907.         necessarily drop to indicate how much you really have left.  This 
  908.         is  because heap space is gathered in blocks of 16K,  not all  at 
  909.         once as with atoms and cells.  So, there will almost certainly be 
  910.         more  than 20% free heap space in other non compacted blocks even 
  911.         if memstat reports 80% of the heap space is in use.                   
  912.  
  913.  
  914.  
  915.                                        15
  916.  
  917.  
  918.  
  919.              FUNCTIONS WITH SIDE EFFECTS OR THAT ARE EFFECTED BY SYSTEM
  920.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  921.              CONT'D
  922.              ~~~~~~
  923.  
  924.              (oblist)
  925.              ~~~~~~~~
  926.              Returns  a  list of every known object in the system at  the 
  927.         current  moment.  Note  that if you call oblist  and  assign  the 
  928.         result  somewhere you will cause every one of those objects to be 
  929.         kept  by the system.  If there are lots of large alpha atoms  the 
  930.         heap  and alpha space will be tied up until you set the  assigned 
  931.         variable to some other value.
  932.  
  933.              (plist a1)
  934.              ~~~~~~~~~~
  935.              Will return the property list for atom a1. The property list 
  936.         is of the form ((ke1 . value1)(key2 . value2)...(keyn . valuen)). 
  937.         Note  that  plist returns a top level copy of the  property  list 
  938.         because remprop destroys this lists top level structure. 
  939.  
  940.              (putd a1 l1)
  941.              ~~~~~~~~~~~~
  942.              Identical  to "def" except that the parameters a1 and l1 are 
  943.         evaluated.  This  allows  you  to  write  functions  that  create 
  944.         functions and add them to the LISP interpreter.
  945.              
  946.              (putprop a1 s1 a2)
  947.              ~~~~~~~~~~~~~~~~~~
  948.              Adds to the property list of a1 the value s1 associated with 
  949.         the  property  indicator a2.  It returns the  value  of  a1.  For 
  950.         example: (putprop 'Peter 'AshwoodSmith 'lastname)
  951.  
  952.              (remprop a1 a2)
  953.              ~~~~~~~~~~~~~~~
  954.              Removes  the  property  associated  with  key  a2  from  the 
  955.         property list of atom a1. The top level structure of the property 
  956.         list  is  actually destroyed.  It returns the old  property  list 
  957.         starting at the point where the deletion was made.
  958.  
  959.              (set a1 s1)
  960.              ~~~~~~~~~~~  
  961.              Will  bind a1 to s1 at current scope level or globally if no 
  962.         scope exists for a1 yet. Set returns s1.
  963.  
  964.              (setplist a1 l1)
  965.              ~~~~~~~~~~~~~~~~
  966.              Will  set the property list of atom a1 to the list l1  where 
  967.         the  list must be ((keyn.valn)..). It returns this new list l1.
  968.  
  969.              (setq *a1* s1 *a2* s2 ..... *an* sn)
  970.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  971.              Allows an infinite number of variable and value pairs and it 
  972.         does  not  evaluate the variables a1...an.  So (setq  a  'val1  b 
  973.         'val2) binds val1 to a and val2 to b. Setq will return sn.
  974.  
  975.  
  976.                                        16
  977.  
  978.  
  979.  
  980.              FUNCTIONS WITH SIDE EFFECTS OR THAT ARE EFFECTED BY SYSTEM
  981.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  982.              CONT'D
  983.              ~~~~~~
  984.              
  985.              (trace [*a1* *a2* *a3* ..... *an*])
  986.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  987.              Will  turn on tracing of the user defined functions a1...an. 
  988.         Note that you cannot trace built in functions.  If you call trace 
  989.         with  no  parameters it will return a list of  all  user  defined 
  990.         functions  that  have been set for tracing by a previous call  to 
  991.         trace,  otherwise  trace  returns exactly the list  (a1  a2...an) 
  992.         after  enabling tracing of each of these user defined  functions. 
  993.         If  any  of the atoms is not a user defined function trace  stops 
  994.         and returns an error.  All atoms up to the point of error will be 
  995.         traced.   
  996.              
  997.              (untrace [*a1* *a2* *a3* ..... *an*])
  998.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  999.              Will  disable tracing of the listed functions which must all 
  1000.         be user defined.  If no parameters are given it disables  tracing 
  1001.         of  all functions.  Untrace returns a list of all functions whose 
  1002.         tracing has been disabled. Here is a demonstration of how you can 
  1003.         use  them.  The  -->  is the LISP prompt.  This is  the  sort  of 
  1004.         sequence  that you should see on the console.  The comments  ;... 
  1005.         were added to tell you what is going on.
  1006.  
  1007.           -->(defun factorial(n)                ; define n! = n * (n-1)!
  1008.                     (cond ((= n 0) 1)
  1009.                           (t (* n (factorial (- n 1))))))
  1010.  
  1011.           factorial
  1012.           -->(trace factorial)                  ; ask LISP to trace n!
  1013.           (factorial)
  1014.           -->(factorial 5)                      ; ask LISP for 5!
  1015.           <enter> factorial( 5 )                ; entered with parm=5
  1016.            <enter> factorial( 4 )               ;    "      "    "  4
  1017.             <enter> factorial( 3 )              ;    "      "    "  3
  1018.              <enter> factorial( 2 )             ;    "      "    "  2
  1019.               <enter> factorial( 1 )            ;    "      "    "  1
  1020.                <enter> factorial( 0 )           ;    "      "    "  0
  1021.                <EXIT>  factorial 1              ; exit 0! = 1
  1022.               <EXIT>  factorial 1               ; exit 1! = 1
  1023.              <EXIT>  factorial 2                ; exit 2! = 1
  1024.             <EXIT>  factorial 6                 ; exit 3! = 6
  1025.            <EXIT>  factorial 24                 ; exit 4! = 24
  1026.           <EXIT>  factorial 120                 ; exit 5! = 120
  1027.           120
  1028.           -->(untrace factorial)                ; ask LISP to shut up
  1029.           (factorial)
  1030.           -->(factorial 5)                      ; now it is quiet again.
  1031.           120
  1032.           -->   
  1033.  
  1034.  
  1035.  
  1036.  
  1037.                                        17
  1038.  
  1039.  
  1040.  
  1041.              FUNCTIONS WITH SIDE EFFECTS OR THAT ARE EFFECTED BY SYSTEM
  1042.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1043.              CONT'D
  1044.              ~~~~~~
  1045.  
  1046.              (showstack)
  1047.              ~~~~~~~~~~~
  1048.                   This  function will display a copy of the last 20  eval 
  1049.         and  apply  evaluations from the internal stack.  The top of  the 
  1050.         internal  stack  is copied whenever LISP is about  to  enter  the 
  1051.         break level (prompt 'er>').   This means that if you execute some 
  1052.         function  and  it aborts prematurely you can call showstack  from 
  1053.         the break level and see exactly what lead to the error.  Whenever 
  1054.         a  new  error occurs the old copy of the top 20 elements  on  the 
  1055.         internal  stack  is  lost and a new trace is copied  for  you  to 
  1056.         display  via  (showstack).  This  is unlike  Franz  which  allows 
  1057.         infinite break levels.  For example consider this example session 
  1058.         with PC-LISP which is similar to an example in LISPcraft.
  1059.                        
  1060.              -->(defun foobar(y)(prog(x)(setq x (cons (car 8) y]
  1061.              foobar
  1062.              -->(foobar '(a b c))
  1063.              --- error evaluating built in function [car] ---
  1064.              er>x
  1065.              ()
  1066.              er>y
  1067.              (a b c)
  1068.              er>(showstack)
  1069.  
  1070.              [] (car 8)
  1071.              [] (car 8)
  1072.              [] (cons <**> y)
  1073.              [] (setq x <**>)
  1074.              [] (prog(x) <**>)
  1075.              [] (foobar '(a b c))
  1076.  
  1077.              t 
  1078.  
  1079.              In  this example I declared a function called 'foobar' which 
  1080.         runs a prog and does a single assignment to x.  When I execute it 
  1081.         with  parameter '(a b c).  PC-LISP correctly tells me that  there 
  1082.         was  an  error  evaluating the built in  function  'car'.  I  can 
  1083.         examine  the values of x and y and see that x is still set to the 
  1084.         empty  list () that the prog call set it to.  y is bound  to  the 
  1085.         parameter passed to foobar as expected. Next I called (showstack) 
  1086.         to see the trace of execution. I see that the top evaluation (car 
  1087.         8)  is the culprit.  The evaluation previous to that is also (car 
  1088.         8)  but  this  evaluation  was  before  the  arguments  had  been 
  1089.         evaluated.  Remember  that floats eval to  themselves.  The  <**> 
  1090.         symbols  in  the show stack are just a short hand way  of  saying 
  1091.         look  at the entry above to see what the <**> should be  replaced 
  1092.         with.  This  greatly  reduces the amount of information that  you 
  1093.         have to look at when you read a stack dump. It also allows you to 
  1094.         follow the stream of partial evaluations by looking at each  <**> 
  1095.         in turn. Note that infinite recursion leaves a stream of <**>'s.
  1096.  
  1097.  
  1098.                                        18
  1099.  
  1100.  
  1101.  
  1102.              LIST EVALUATION CONTROL FUNCTIONS
  1103.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1104.              These functions are the control flow functions for LISP they 
  1105.         effect  which  lists are evaluated and how.  They operate on  the 
  1106.         basic  LISP function type which is a lambda  expression.  Labeled 
  1107.         lambda expressions are also allowed.
  1108.  
  1109.              (lambda l1 s1....sn)
  1110.              ~~~~~~~~~~~~~~~~~~~~
  1111.              This  is  not a function but it is a  list  construct  which      
  1112.         can act as a function in any context where a function is legal. A 
  1113.         lambda  expression is a function body.  The S-expressions  s1..sn 
  1114.         are  expressions  that are evaluated in the  order  s1...sn.  The 
  1115.         result  is  the evaluation of sn.  The atoms in the list  l1  are 
  1116.         called  bound variables.  They will be bound to values that occur 
  1117.         on  the right of the lambda expression before  the  S-expressions 
  1118.         s1..sn  are  evaluated  and  unbound after the  value  of  sn  is 
  1119.         returned. 
  1120.  
  1121.              (nlambda l1 s1....sn)
  1122.              ~~~~~~~~~~~~~~~~~~~~~
  1123.              This is a function body construct similar to lambda but with 
  1124.         a few major differences.  The first is that the list l1 must only 
  1125.         specify  one formal parameter.  This will be set to a list of the 
  1126.         UNEVALUATED  parameters  that  fall on the right of  the  nlambda 
  1127.         expression when it is being evaluated.  This function allows  you 
  1128.         to  write  functions with a variable number of parameters and  to 
  1129.         control  the evaluation of these parameters.  For example we  can 
  1130.         write a function called 'plus that behaves the same way as '+  in 
  1131.         all contexts as follows:
  1132.  
  1133.              -->(def plus (nlambda(l)(eval(cons '+ l))))  
  1134.         or   
  1135.              -->(defun plus fexpr(l)(eval(cons '+ l)))
  1136.  
  1137.              Both  of  which create the  same  nlambda  expression.  This 
  1138.         function  will  behave as follows when spotted on the left  of  a 
  1139.         sequence  of parameters 1 2 3 4.  First it will not evaluate  the 
  1140.         sequence of parameters 1 2 3 4. Second it makes these into a list 
  1141.         (1  2  3  4).  It then binds 'l to this list  and  evaluates  the 
  1142.         expression (eval(cons( '+ l))).  This expression results in (eval 
  1143.         (+ 1 2 3 4)). Which is just the desired result 10.
  1144.  
  1145.              (label a1 (lambda|nlambda l1 s1..sn)) 
  1146.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1147.              This acts just like a lambda expression except that the body 
  1148.         is  temporarily  bound to the name a1 for evaluation of the  body 
  1149.         s1.  This allows recursive calls to the same body. The binding of 
  1150.         the  body  to  the  name a1 will be  forgotten  as  soon  as  the 
  1151.         expression s1 terminates the recursion. For example:   
  1152.  
  1153.              (label LastElement (lambda(List)
  1154.                                 (cond ((null (cdr List))(car List))
  1155.                                       (t (LastElement (cdr List))))))
  1156.  
  1157.  
  1158.  
  1159.                                        19
  1160.  
  1161.  
  1162.  
  1163.              LIST EVALUATION CONTROL FUNCTIONS CONT'D
  1164.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1165.              (apply s1 l1)
  1166.              ~~~~~~~~~~~~~
  1167.              The  function s1 is evaluated in the context resulting  from 
  1168.         binding  its formal parameters to the values in l1. The result of 
  1169.         this evaluation is returned. Example:
  1170.  
  1171.              -->(apply '(lambda(x y z)(* (+ x y) z)) '(2 3 4))
  1172.              20
  1173.              
  1174.              (cond l1 l2 ... ln)
  1175.              ~~~~~~~~~~~~~~~~~~~
  1176.              The lists l1 ...  ln  are checked on by one. They are of the 
  1177.         form  (s1 s2). Cond  evaluates the s1's one by one until it finds 
  1178.         one  that does not eval to nil.  It then returns the  result   of  
  1179.         evaluating   the corresponding  s2.  If all of the  s1's  (called 
  1180.         guards) evaluate to nil, it returns 'nil. For example:
  1181.                   
  1182.               -->(cond ((eq (type t) 'float) '|t is a float|)
  1183.                        ((eq (type t) 'list)  '|t is a list |)
  1184.                        (t '|t not list or float|)))
  1185.              |t not list or float|
  1186.  
  1187.              (eval s1) 
  1188.              ~~~~~~~~~
  1189.              Runs  the LISP interpreter on the S-expression s1.  It  just 
  1190.         removes a quote from the expression s1. For example:
  1191.              
  1192.              -->(eval '(+ 2 4))
  1193.              6
  1194.  
  1195.              (mapcar s1 l1 l2 l3 .... ln)
  1196.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1197.              This  function  will map the function s1 onto the  parameter 
  1198.         list made by taking the car of each of l1...ln.  It forms a  list 
  1199.         of  the  results  of the repeated application of s1 to  the  next 
  1200.         elements in the lists l1...ln. It stops when the list l1 runs out 
  1201.         of  elements.  Note  that each of l1...ln should  have  the  same 
  1202.         number  of elements,  although this condition is not checked  for 
  1203.         and nil will be substituted if a list runs out of elements before 
  1204.         the others. Extra elements in any list are ignored. For example:
  1205.  
  1206.              -->(mapcar '< '(10 20 30) '(11 19 30))
  1207.              (t nil nil)
  1208.  
  1209.              Which  returns the results of (< 10 11) (< 20 19) and (<  30 
  1210.         30) as the list (t nil nil).  Note that s1 could be any built  in 
  1211.         function,   user  defined  function  or  lambda  expression.  For 
  1212.         example:
  1213.  
  1214.              -->(mapcar 'putprop '(John Fred Bill)
  1215.                                  '(Mary Sue Linda)
  1216.                                  '(mother sister daughter))
  1217.              (Mary Sue Linda) 
  1218.  
  1219.  
  1220.                                        20
  1221.  
  1222.  
  1223.  
  1224.              LIST EVALUATION CONTROL FUNCTIONS  CONT'D
  1225.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1226.  
  1227.              (defun a1 macro l1 s1 s2 ... sn)
  1228.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     
  1229.              Macro  is a special body,  similar to nlambda except that it 
  1230.         causes code replacement when it is evaluated.  An example is  the 
  1231.         best explanation  I can give you: (Read LISPcraft example)
  1232.  
  1233.              -->(defun first-elemet macro(l)(cons 'car (cdr l)))
  1234.              first-element
  1235.              -->(setq x '(first-element '(a b c)))
  1236.              (first-element '(a b c)) 
  1237.              -->(eval x)
  1238.              a
  1239.              -->x
  1240.              (car '(a b c)) 
  1241.              -->(eval x)
  1242.              a
  1243.  
  1244.              In  the  example above I have first declared a macro  called 
  1245.         'first-element'  which  when run given a  list  parameter  should 
  1246.         return  the  first element in the list.  I could have  done  this 
  1247.         using  a  lambda  expression  but this  would  require  parameter 
  1248.         binding etc every time I execute 'first-element'.  Rather, what I 
  1249.         have chosen to do is to cause (first-element x) to be replaced by 
  1250.         the  code  (car  x) everywhere it  is  encountered.  Then  future 
  1251.         execution of (first-element x) is just as costly as an  execution 
  1252.         of  (car  x).  This is accomplished as follows:  When a macro  is 
  1253.         encountered,  eval  passes the entire  expression  (first-element 
  1254.         (quote  a b c)) to the macro body.  This body is (cons 'car  (cdr 
  1255.         l))  and is evaluated in the context where the entire  expression 
  1256.         is  bound  to  the macro parameter l.  This results in  the  code 
  1257.         fragment (car (quote a b c)) which is substituted in the code for 
  1258.         the  original  (first-element  (quote (a b  c)))  expression  and 
  1259.         evaluated  giving  'a.  The above example  demonstrates  this  by 
  1260.         showing  what  happens to the value of a variable 'x  before  and 
  1261.         after evaluation of the macro.  Note the change in the value of x 
  1262.         but  that  the result of (eval x) remains the same.  That is  the 
  1263.         whole purpose of macros.
  1264.  
  1265.              PC-LISP macros have two limitations that Franz macros do not 
  1266.         have. A PC-LISP macro MUST return a piece of code that is a list. 
  1267.         YOU CANNOT RETURN AN ATOM FROM A MACRO.  Secondly a PC-LISP macro 
  1268.         must  have been def'ined,  defun'ed,  or  putd'ed,  otherwise  it 
  1269.         will  not function correctly.  Ie YOU CANNOT USE IT LIKE A LAMBDA 
  1270.         OR NLAMBDA BODY WITHOUT A NAME.
  1271.  
  1272.              (macroexpand s1)
  1273.              ~~~~~~~~~~~~~~~~     
  1274.              This function lets you see at what the macro expansion of s1 
  1275.         looks like prior to evaluation and substitution. For example:
  1276.  
  1277.              -->(macroexpand '(first-element '(a b c)))
  1278.              (car '(a b c))
  1279.  
  1280.  
  1281.                                        21
  1282.  
  1283.  
  1284.  
  1285.              LIST EVALUATION CONTROL FUNCTIONS  CONT'D
  1286.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1287.  
  1288.              (prog l1 s1.....sn)
  1289.              ~~~~~~~~~~~~~~~~~~~
  1290.              Prog  is  a  way  of  escaping  the  pure  LISP  applicative 
  1291.         programming environment.  It allows you to evaluate a sequence of 
  1292.         S-expressions  one after the other in true imperative  style.  It 
  1293.         allows you to use the functions (go..) and (return ..) to perform 
  1294.         the  goto and return functions that imperative languages  permit. 
  1295.         Prog  operates  as follows:  The list l1 which is a list of  atom 
  1296.         names  is  scanned and each atom is bound to nil  at  this  scope 
  1297.         level.  Next the S-expressions s1..sn are scanned once. If any of 
  1298.         s1..sn  are atoms they are bound to the S-expression that follows 
  1299.         them.  Next we start evaluating lists s1...sn ignoring  the atoms 
  1300.         which  are  assumed  to  be labels.  If we  ever  evaluate  a  S-
  1301.         expression and it has the form (return Z) we unbind all the atoms 
  1302.         in  l1  and  all labels,  and return the result  Z.  If  we  ever 
  1303.         encounter  a list of the form (go loc) we reset our next list  to 
  1304.         be the location given by loc.  If at any time we reach sn, and it 
  1305.         is  not  a go or a return,  we simply unbind all of  l1  and  the 
  1306.         labels  in  s1...sn  and  return the  result  of  evaluating  sn. 
  1307.         Entering and exiting progs is a little expensive time wise, it is 
  1308.         probably  better  not  to  nest them if  you  are  interested  in 
  1309.         performance.  Note  prog  labels must be alpha or  literal  alpha 
  1310.         atoms:
  1311.              
  1312.              For example:
  1313.  
  1314.                -->(prog (List SumOfAtoms)
  1315.                         (setq List (hashtabstat))
  1316.                         (setq SumOfAtoms 0)
  1317.                    LOOP (cond ((null List) (return SumOfAtoms)))
  1318.                         (setq SumOfAtoms (+ (car List) SumOfAtoms))
  1319.                         (setq List (cdr List))
  1320.                         (go   LOOP)
  1321.                   )
  1322.                306  
  1323.  
  1324.              This peice of code operates as follows. First it creates two 
  1325.         local variables.  Next it binds the variable List to the list  of 
  1326.         hash bucket totals from the alpha hash table.  It then sets a sum 
  1327.         counter  to 0.  Next it checks the List variable to see if it  is 
  1328.         nil. If so it returns the Sum Of all the Atoms. Otherwise it adds 
  1329.         the first float in the list List to the running SumOfAtoms, winds 
  1330.         in the list List by one, and jumps to LOOP. Note also that we can 
  1331.         accomplish the same thing as the above prog with the much simpler 
  1332.         examples which follow:
  1333.  
  1334.              -->(eval (cons '+ (hashtabstat)))
  1335.              306
  1336.              -->(length(oblist))
  1337.              306
  1338.  
  1339.  
  1340.  
  1341.  
  1342.                                        22
  1343.  
  1344.  
  1345.  
  1346.              MSDOS BIOS CALLS FOR GRAPHICS OUTPUT
  1347.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1348.              These  functions  are still experimental.  They  do  however 
  1349.         allow  you  to  play  with drawing  recursive  curves  etc.  They      
  1350.         all  result  in  an  INT  10H.   This  means  that  the  graphics      
  1351.         should be portable to any MSDOS machine and should run under  any 
  1352.         windowing environment like topview or mswindows. This is why they 
  1353.         are so slow.  Note that they all return 't.  They do not check to 
  1354.         see if the INT call was successful or not.
  1355.  
  1356.              (#scrline# f1 f2 f3 f4 f5)
  1357.              ~~~~~~~~~~~~~~~~~~~~~~~~~~
  1358.              Draws a line on the screen connecting (f1,f2) with the point 
  1359.         (f3,f4) using attribute f5.  This function calls the BIOS set dot 
  1360.         function for each point. Hence it is not very fast.
  1361.  
  1362.              (#scrmde# f1)
  1363.              ~~~~~~~~~~~~~
  1364.              Sets the video mode to f1. Modes are values between 0 and 9. 
  1365.         (8 and 9) are high resolution for the Tandy2000 and I suppose are 
  1366.         high  resolution modes on other machines that support  the (640 x 
  1367.         400)  or greater graphics resolutions.  These are all  listed  in 
  1368.         your  hardware  reference  manual but basically  they  are:  0  = 
  1369.         40x25B&W,  1=40x25COL,  2=80x25B&W  3=80x25COL,   4  =320x200COL,  
  1370.         5=320x200B&W,      6=640x200B&W,     7=reserved,    8=640x400COL, 
  1371.         9=640x400B&W. This is as of DOS 2.11.
  1372.  
  1373.              (#scrsap# f1)
  1374.              ~~~~~~~~~~~~~
  1375.              Sets the active video page to f1. f1 should be between 0 and 
  1376.         8.  This  is valid for text modes only.  Versions of MSDOS  other 
  1377.         than 2.11 may not support this call.
  1378.  
  1379.              (#scrscp# f1 f2 f3)
  1380.              ~~~~~~~~~~~~~~~~~~~
  1381.              Sets  the cursor position to be in page f1 at row f2 and  in 
  1382.         column f3. Where 0 is the top row and 0 is leftmost col.
  1383.  
  1384.              (#scrsct# f1 f2)
  1385.              ~~~~~~~~~~~~~~~~
  1386.              Sets  the  cursor  type to agree with the following:  f1 bit 
  1387.         5  (0 = blink 1 = steady),  bit 6 (0 = visible,  1 =  invisible), 
  1388.         bits  4-0 = start line for cursor within character cell.  f2 bits 
  1389.         4-0 = end line for cursor within character cell.
  1390.  
  1391.              (#scrwdot# f1 f2 f3)
  1392.              ~~~~~~~~~~~~~~~~~~~~
  1393.              Write a dot (pixel).  The pixel at row f1 and column f2  has 
  1394.         its  color  value XORed with the color attribute  f3.  Since  the 
  1395.         color  attributes  vary from machine to machine you will have  to 
  1396.         look up the correct values for this parameter.
  1397.  
  1398.  
  1399.  
  1400.  
  1401.  
  1402.  
  1403.                                        23
  1404.  
  1405.  
  1406.  
  1407.              TECHNICAL INFORMATION
  1408.              ~~~~~~~~~~~~~~~~~~~~~
  1409.  
  1410.              The  interpreter  is written using the  Lattice  C  compiler 
  1411.         version  2.03.  It  consists of 7 separate  modules.  A  scanner, 
  1412.         parser,  memory  manager,  list evaluator and critical  functions 
  1413.         module, a built in functions module, a library of extra Unix libc 
  1414.         functions not  provided  by  Lattice  C  consisting  of  assembly 
  1415.         language  routines  for setjmp(),  longjmp()  and  getenv(),  and 
  1416.         finally a modified C start up assembly language module to provide 
  1417.         signal trapping for stack overflow and control-break.
  1418.  
  1419.              Memory is organized as follows.  Alpha cells have fields for 
  1420.         a  shallow  stack of bindings,  a pointer to heap space  for  the 
  1421.         print names, a pointer to any built in or user defined functions, 
  1422.         and a pointer to any property lists.  Alpha cells are the largest 
  1423.         of  all  the cells and have their own fixed  storage  area.  Heap 
  1424.         space  which  is just the space used for the print names  of  the 
  1425.         alpha cells may be variable sized blocks of up to 254 bytes long. 
  1426.         These  will  be extended in future versions of PC-LISP  to  allow 
  1427.         allocation of up to 64K blocks for use by arrays etc. The rest of 
  1428.         the  cells  used  by  PC-LISP are all  considered  as  one.  This 
  1429.         consists of the float,  cons, and port cells. They have their own 
  1430.         contiguous  slice  of memory.  This means  that  three  different 
  1431.         contiguous  types  of memory are required.  It is managed in  the 
  1432.         following  way.  At start up time the percentages of  memory  are 
  1433.         read  from  the  default settings or  the  environment  variables 
  1434.         LISP%HEAP and LISP%ALPH.  Next memory is allocated in 16K  chunks 
  1435.         these   are  the  largest  contiguous  pieces  handled   by   the 
  1436.         memory manager.  These are all kept track of in a large vector of 
  1437.         pointers.  Next  groups  of  these blocks are primed for  use  by 
  1438.         alpha,cell,   or  heap  managers.   These  managers  handle   the 
  1439.         distribution and reclamation  of memory in their block.  The heap 
  1440.         manager will perform compaction and relocation to get free space. 
  1441.         The  alpha and cell managers will perform mark and gather garbage 
  1442.         collection  to get space.  The heap manager may request mark  and 
  1443.         gather collection if there is a real shortage of heap space.
  1444.  
  1445.              Stack overflow detection is done by intercepting the call to 
  1446.         the  Lattice C stack overflow routine,  temporarily resetting the 
  1447.         stack, and them making a call to my own C stack overflow routine. 
  1448.         This then longjmps out of the error condition.  The Unix  version 
  1449.         handles  the  error  in  the same way except  that  the  overflow 
  1450.         results in a SIGSEGV which then calls the same routine.
  1451.  
  1452.              Control-BREAK detection is done via periodic testing of  the 
  1453.         status in the evaluator main loop, and the read main loop. When a 
  1454.         break  is  detected control is transferred to the  break  handler 
  1455.         which  prints  a message and longjmps back to the mainline  code. 
  1456.         The  Unix  version will have made a signal call asking  that  the 
  1457.         break handler be executed when a user break key is hit. Hence the 
  1458.         results are the same.  CONTROL-C checking is done in the same way 
  1459.         except that a CONTROL-C will only be spotted on I/O so a  looping 
  1460.         non  printing  function can only be stopped  with  CONTROL-BREAK. 
  1461.         Note that CONTROL-BREAK is INT 1BH and CONTROL-C is INT 23H.
  1462.  
  1463.  
  1464.                                        24
  1465.  
  1466.  
  1467.  
  1468.              KNOWN BUGS OR LACKING FEATURES OF V2.07
  1469.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1470.  
  1471.             -It  is  possible  to run out of stack  space  while  garbage 
  1472.         collecting.  This  occasionally  happens with machines that  have 
  1473.         only 256K of RAM. I have never seen it happen with >  256K of RAM 
  1474.         however it can probably still happen. This is because the garbage 
  1475.         collector  requires stack space to operate.  A better version  of 
  1476.         the  garbage  collection  that  uses  no  stack  space  will   be 
  1477.         introduced in a later version.  If the stack does overflow during 
  1478.         garbage  collection, an appropriate error message is  printed.  A 
  1479.         link  inverting marking traversal is slated for the next  version 
  1480.         of PC-LISP and will fix this problem.
  1481.  
  1482.             -You  cannot  input floats in exponential notation.  This  is 
  1483.         because the LISP lexical analyzer does not yet recognize them.
  1484.  
  1485.             -Line drawing is not too quick,  or too clean. The lines take 
  1486.         time to draw because they go through the BIOS,  they are not very 
  1487.         clean at certain slopes due to some bugs.  But the video graphics 
  1488.         routines  are still experimental so do not rely on them too much. 
  1489.         You  will  also  note  that several other  video  INT  calls  are 
  1490.         missing.
  1491.  
  1492.             -If  too  many  (load 'file) calls fail you will run  out  of 
  1493.         available ports. This is because they are left open. PC-LISP does 
  1494.         not  close open load ports if an error occurs while reading  from 
  1495.         them.
  1496.  
  1497.             -Two  special atoms with rather obscure names should never be 
  1498.         printed from within a prog.  These are $[|return|]$ and $[|go|]$. 
  1499.         If  you  attempt to print these from within  a  prog,  the  print 
  1500.         function  will return them and this will confuse the heck out  of 
  1501.         prog which uses them for internal purposes. This can occur if you 
  1502.         try  to use a prog to print the contents of the  oblist.  If  you 
  1503.         must print the oblist atom by atom to a file or the screen,  make 
  1504.         sure you 'absorb' the result of any print or patom calls.
  1505.  
  1506.             -You  are  not prevented from altering the bindings of t  and 
  1507.         nil.  This  means  that  if you use t or nil as  the  name  of  a 
  1508.         parameter  somewhere  it will get temporarily bound to  something 
  1509.         else while that procedure is executing.  You can also set or setq 
  1510.         them  to other values.  Attempts to alter their  bindings  should 
  1511.         obviously be trapped but are not in V2.07.
  1512.  
  1513.             -Macros  must return a peice of code which is a  list.  Atoms 
  1514.         cannot  be  returned.  Franz allows either but to  alter  PC-LISP 
  1515.         would  require  some medium scale surgery that I do not  want  to 
  1516.         undertake unless the feature is really missed.
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523.  
  1524.  
  1525.                                        25
  1526.  
  1527.  
  1528.  
  1529.              KNOWN BUGS OR LACKING FEATURES OF V2.07 (CONT'D)
  1530.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1531.  
  1532.             -The  interpreter  is  pretty slow.  This is  caused  by  the 
  1533.         continuous  error  checking,  and the use of an extra  stack  for 
  1534.         marking intermediate results. Speed-ups are possible but make the 
  1535.         program  less robust so I am hesitant to add them.  The fact that 
  1536.         there  is  no integer type also causes slow-downs  when  you  are 
  1537.         using  a float as a loop counter.  Floats however are more useful 
  1538.         in general than ints so of the two I decided to omit integers for 
  1539.         the  first large scale release.  It is interesting to  note  that 
  1540.         some benchmarks that I ran on a not too busy Vax 11/750 were only 
  1541.         about  2 times as fast (waiting time) as my Tandy 2000  (80186  @ 
  1542.         8Mhz). This is not really a fair comparison  though because Franz 
  1543.         is a much bigger and more complex program.  I would be interested 
  1544.         to know how PC-LISP performs on other MS-DOS machines.
  1545.              
  1546.              RE BUGS OR DESIRED ENHANCMENTS
  1547.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1548.              I have tried to think of everything that a user could do  to 
  1549.         crash  the  system  and protect him/her from it but I'm  sure  my 
  1550.         imagination  has only covered half of the possibilities.  If  you 
  1551.         find  any other bugs or if you think some features would be  nice 
  1552.         to  add  to  PC-LISP,  I will consider them for  the  next  major 
  1553.         release (which will probably not be until September  86).  Please 
  1554.         don't  hesitate to let me know what you think,  good or bad.  I'd 
  1555.         appreciate  the feed back as I have put a lot of work  into  this 
  1556.         program and want to know what you people out there think of it.
  1557.              
  1558.  
  1559.  
  1560.                                Regards  
  1561.  
  1562.              
  1563.                           Peter Ashwood-Smith.
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580.  
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.                                        26
  1587.  
  1588.